
from utils.common import to_array, to_variable, to_tuple
import weakref

from core.config import Config


# 方法基类
class Function:

    # Function的__call__方法将实际数据从Variable这个“箱子”里取出，
    # 然后通过 forward方法进行具体的计算。
    # 然后，它把结果封装在Variable中并让结果记住Function是它的“创造者”。

    def __call__(self, *inputs):
        # to_variable 将inputs中的变量包裹为Variable
        inputs = [to_variable(x) for x in inputs]
        xs = [x.data for x in inputs]
        ys = self.forward(*xs)
        # 输出的变量包裹为Variable
        outputs = [to_variable(to_array(y)) for y in to_tuple(ys)]  # 使用辅助函数转换成元组

        # 不需要不必要的中间的梯度
        if Config.enable_backprop:
            # 辈分，表示函数（或变量）属于哪一代
            self.generation = max([x.generation for x in inputs])
            for output in outputs:
                output.set_creator(self)

            self.inputs = inputs
            # 弱引用可以在不增加引用计数的情况下引用另一个对象的功能，主要是为了避免循环引用
            self.outputs = [weakref.ref(output) for output in outputs]

        return outputs if len(outputs) > 1 else outputs[0]

    # 前向传播
    def forward(self, *args):
        raise NotImplementedError("Subclasses must implement the forward method.")

    # 反向传播
    def backward(self, *grad_outputs):
        raise NotImplementedError("Subclasses must implement the backward method.")

